package com.dikeleakagedetection.myapplication.wiget

import android.content.Context
import android.graphics.*
import android.text.TextUtils
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.dikeleakagedetection.myapplication.R
import com.dikeleakagedetection.myapplication.logic.model.RelativeDot
import com.dikeleakagedetection.myapplication.utils.InterpolationUtils

class ContourChart @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private var mPaint: Paint

    //自定义样式
    private var mCounterChartTitle: String? = null
    private var mTextSize = 0f

    //初始参数
    private var stateInfo = arrayOf(
        doubleArrayOf(6.0, 4.0, 3.0, 3.0, 3.0, 3.0, 4.0, 6.0),
        doubleArrayOf(5.0, 3.0, 2.0, 2.0, 2.0, 2.0, 3.0, 5.0),
        doubleArrayOf(6.0, 4.0, 3.0, 3.0, 3.0, 3.0, 4.0, 6.0)
    )
    private var length = (stateInfo[0].size - 1).toDouble()
    private var width = (stateInfo.size - 1).toDouble()
    private var amplification = 200

    fun setStateInfo(stateInfo: Array<DoubleArray>, length: Double, width: Double, amplification: Int) {
        this.stateInfo = stateInfo
        this.length = length
        this.width = width
        this.amplification = amplification
    }

    //绘图
    private var originalX = 0f
    private var originalY = 0f

    init {
        //获取自定义样式
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ContourChart)
        mCounterChartTitle = typedArray.getString(R.styleable.ContourChart_counterChartTitle)
        mTextSize = typedArray.getDimension(R.styleable.ContourChart_textSize, 30f)
        typedArray.recycle()

        mPaint = Paint().apply {
            isDither = true //防抖
            isAntiAlias = true //抗锯齿
            style = Paint.Style.FILL //填充模式
        }

        val dotList = ArrayList<RelativeDot>()
        initData(dotList)
        stateInfo = InterpolationUtils.interpolation(dotList, 7, 2, 200)!!
        Log.e("ColorView", "${stateInfo.size}/${stateInfo[0].size}")
        /*for (i in stateInfo.indices) {
            Log.e("ColorView", stateInfo[i].contentToString())
        }*/

        length = 7.0
        width = 2.0
        amplification = 200
    }

    private fun initData(dotList: ArrayList<RelativeDot>) {
        dotList.add(RelativeDot(0,0,6.0))
        dotList.add(RelativeDot(0,1,4.0))
        dotList.add(RelativeDot(0,2,3.0))
        dotList.add(RelativeDot(0,3,3.0))
        dotList.add(RelativeDot(0,4,3.0))
        dotList.add(RelativeDot(0,5,3.0))
        dotList.add(RelativeDot(0,6,2.0))
        dotList.add(RelativeDot(0,7,6.0))
        dotList.add(RelativeDot(1,0,5.0))
        dotList.add(RelativeDot(1,1,3.0))
        dotList.add(RelativeDot(1,2,2.0))
        dotList.add(RelativeDot(1,3,2.0))
        dotList.add(RelativeDot(1,4,1.0))
        dotList.add(RelativeDot(1,5,2.0))
        dotList.add(RelativeDot(1,6,3.0))
        dotList.add(RelativeDot(1,7,4.0))
        dotList.add(RelativeDot(2,0,6.0))
        dotList.add(RelativeDot(2,1,4.0))
        dotList.add(RelativeDot(2,2,3.0))
        dotList.add(RelativeDot(2,3,3.0))
        dotList.add(RelativeDot(2,4,2.0))
        dotList.add(RelativeDot(2,5,2.0))
        dotList.add(RelativeDot(2,6,4.0))
        dotList.add(RelativeDot(2,7,5.0))
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        //初始化数据
        //val paintColor = intArrayOf(-16776961, -7829368, -65536, -256, -16777216, -16711681, -12303292) //蓝，灰，红，黄，黑, 蓝绿, 深灰
        val paintColor = intArrayOf(-16776961, -7829368, -65536) //蓝，灰，红，黄，黑, 蓝绿, 深灰
        val cell = DoubleArray(paintColor.size)

        initCell(cell, stateInfo)

        drawAxis(originalX, originalY, canvas, mPaint)
        drawAxisName(canvas, mPaint)
        drawContourLine(stateInfo, cell, canvas, mPaint, paintColor)
        drawHint(canvas, mPaint, cell, paintColor)
    }

    //绘制等高线
    private fun drawContourLine(
        stateInfo: Array<DoubleArray>,
        cell: DoubleArray,
        canvas: Canvas?,
        mPaint: Paint,
        paintColor: IntArray
    ) {

        mPaint.style = Paint.Style.STROKE
        mPaint.strokeJoin = Paint.Join.ROUND
        mPaint.pathEffect = CornerPathEffect(80F)

        for (n in cell.indices) {
            val mPath1 = Path()
            val mPath2 = Path()
            for (i in 0 until stateInfo.size - 1) {
                for (m in 0 until stateInfo[i].size - 1) {
                    mPaint.color = paintColor[n]
                    drawContourLineCell(i, m, cell[n], canvas, mPaint, mPath1, mPath2)
                }
            }
            canvas!!.drawPath(Path(mPath1), mPaint)
            canvas.drawPath(Path(mPath2), mPaint)
        }

    }

    //绘制每一个单元格的等高线
    private fun drawContourLineCell(x: Int, y: Int, cell: Double, canvas: Canvas?, mPaint: Paint, mPath1: Path, mPath2: Path) {


        val halfLong = 1f
        val long = 0.5f

        var flag = 0b0000
        if (stateInfo[x][y] >= cell) {
            flag += 0b0001
        }
        if (stateInfo[x][y + 1] >= cell) {
            flag += 0b0010
        }
        if (stateInfo[x + 1][y + 1] >= cell) {
            flag += 0b0100
        }
        if (stateInfo[x + 1][y] >= cell) {
            flag += 0b1000
        }

        val drawX = originalX + x
        val drawY = originalY + y

        when (flag) {
            0 -> {
            }
            1 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            2 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY + long, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            3 -> {
                mPath1.moveTo(drawY, drawX + halfLong)
                mPath1.lineTo(drawY + long, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            4 -> {
                mPath1.moveTo(drawY + long, drawX + halfLong)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            5 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY + long, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
                mPath2.moveTo(drawY, drawX + halfLong)
                mPath2.lineTo(drawY + halfLong, drawX + long)
                //canvas.drawPath(mPath2, mPaint)
            }
            6 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            7 -> {
                mPath1.moveTo(drawY, drawX + halfLong)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            8 -> {
                mPath1.moveTo(drawY, drawX + halfLong)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            9 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            10 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
                mPath2.moveTo(drawY + long, drawX + halfLong)
                mPath2.lineTo(drawY + halfLong, drawX + long)
                //canvas.drawPath(mPath2, mPaint)
            }
            11 -> {
                mPath1.moveTo(drawY + long, drawX + halfLong)
                mPath1.lineTo(drawY + halfLong, drawX + long)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            12 -> {
                mPath1.moveTo(drawY, drawX + halfLong)
                mPath1.lineTo(drawY + long, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            13 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY + long, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            14 -> {
                mPath1.moveTo(drawY + halfLong, drawX)
                mPath1.lineTo(drawY, drawX + halfLong)
                //canvas!!.drawPath(mPath1, mPaint)
            }
            15 -> {
            }
        }


    }

    //绘制颜色说明
    private fun drawHint(canvas: Canvas?, mPaint: Paint, cell: DoubleArray, paintColor: IntArray) {
        mPaint.style = Paint.Style.FILL_AND_STROKE

        val lineX = 900
        val lineY = 500

        for (i in cell.indices) {
            mPaint.textSize = 20f
            mPaint.color = paintColor[i]

            //mPaint.setColor(Color.BLACK);
            mPaint.strokeWidth = 1f
            canvas!!.drawText("-------------" + cell[i].toString(), (lineX + 85).toFloat(), (lineY + i * 30).toFloat(), mPaint)
        }
    }

    //绘制标题
    private fun drawAxisName(canvas: Canvas?, mPaint: Paint) {
        mPaint.style = Paint.Style.FILL_AND_STROKE

        if (!TextUtils.isEmpty(mCounterChartTitle)) {
            mPaint.textSize = mTextSize
            canvas!!.drawText(
                mCounterChartTitle!!,
                getWidth() / 2 - mPaint.measureText(mCounterChartTitle) / 2,
                (originalY + amplification * width + 40).toFloat(),
                mPaint
            )
        }
    }

    //绘制边框
    private fun drawAxis(originalX: Float, originalY: Float, canvas: Canvas?, mPaint: Paint) {
        val mPath = Path()

        mPaint.style = Paint.Style.STROKE

        mPath.moveTo(originalX, originalY)
        mPath.lineTo((originalX + length * amplification).toFloat(), originalY)
        mPath.lineTo((originalX + length * amplification).toFloat(), (originalY + width * amplification).toFloat())
        mPath.lineTo(originalX, (originalY + width * amplification).toFloat())
        mPath.lineTo(originalX, originalY)

        canvas!!.drawPath(mPath, mPaint)
    }

    //根据stateInfo的值进行划分，为cell初始化
    private fun initCell(cell: DoubleArray, stateInfo: Array<DoubleArray>) {
        var max = Double.MIN_VALUE
        var min = Double.MAX_VALUE
        for (i in stateInfo.indices) {
            for (m in stateInfo[i].indices) {
                if (max < stateInfo[i][m]) {
                    max = stateInfo[i][m]
                }
                if (min > stateInfo[i][m]) {
                    min = stateInfo[i][m]
                }
            }
        }

        for (i in cell.indices) {
            cell[i] = min + (max - min) * (i + 1) / (cell.size + 1)
        }
    }

}